package com.huiquan.inspection.service;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.huiquan.analysis.domain.User;
import com.huiquan.foundation.constant.SubmitStatus;
import com.huiquan.foundation.util.BusinessUtil;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.inspection.dao.IndexDao;
import com.huiquan.inspection.domain.Index;
import com.huiquan.inspection.domain.IndexDto;
import com.huiquan.inspection.domain.IndexEncyclopedia;
import com.huiquan.inspection.domain.TestingClass;
import com.huiquan.management.constant.MigrateCode;
import com.huiquan.management.util.MigrateSwitch;

@Service
public class IndexService extends BaseService {

	@Autowired
	private IndexDao indexDao;
	@Autowired
	private TestingClassService testingClassService;

	@Value("${inspection.file.script}")
	private String indexFileScript;

	/**
	 * 获取指标列表
	 * 
	 * @param startStr
	 * @param name
	 * @param originalName
	 * @param exactSearchFlag
	 * @param blankFlag
	 * @return
	 */
	public Map<String, Object> getList(String startStr, String name, String originalName, String exactSearchFlag,
			String blankFlag, String countPerPageStr) {
		int start = startStr == null ? 1 : Integer.parseInt(startStr);
		boolean exactFlag = exactSearchFlag != null && exactSearchFlag.equals("1");

		Map<String, Object> param = new HashMap<>();
		if (name != null && !name.isEmpty()) {
			param.put("name", exactFlag ? name : "%" + name + "%");
		}
		if (originalName != null && !originalName.isEmpty()) {
			param.put("originalName", exactFlag ? originalName : "%" + originalName + "%");
		}

		setBlankFlag(param, blankFlag);
		int totalSize = indexDao.retrieveSize(param);

		Map<String, Integer> pageNo = new HashMap<>();
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "", countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, start + "");
		}
		int endPage = pageNo.get("endPage");
		start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<Map<String, Object>> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = indexDao.retrieveMapList(param);
		}

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("originalName", "原始指标");
		showSearch.put("name", "标准名称");
		Map<String, String> searchMap = new HashMap<>();
		searchMap.put("originalName", originalName);
		searchMap.put("name", name);
		searchMap.put("blankFlag", blankFlag);
		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, searchMap);
		map.put("showSearch", showSearch);
		map.put("showSearchValue", searchMap);
		map.put("exactSearchFlag", exactSearchFlag);

		if (SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_INSPECTION)) {
			map.put("submitFlag", "1");
		}

		return map;
	}

	private void setBlankFlag(Map<String, Object> param, String blankFlag) {
		if (blankFlag == null || blankFlag.isEmpty() || !StringUtils.isNumeric(blankFlag)) {
			return;
		}

		// 根据数字获取那个字段为空，第一位表示含义，第二位表示正常值，第三位表示临床意义，第四位表示注意事项
		int blankNum = Integer.parseInt(blankFlag);
		for (int i = 0; i < 4; i++) {
			if (blankNum ==i) {
				param.put("blank" + i, "1");
			}
		}
	}

	public Map<String, Object> preEdit(String id, User user, String name, String originalName,
			String encyclopediaId, String indexId, String classId) {
		if (id == null || id.trim().isEmpty()) {
			Map<String, Object> map = new HashMap<>();
			return map;
		}

		// 如果没有指标百科则初始化一个
		IndexEncyclopedia indexEncyclopedia = null;
		if ("0".equals(encyclopediaId)) {
			indexEncyclopedia = new IndexEncyclopedia();
			indexEncyclopedia.setIndexId(Long.parseLong(indexId));
			indexEncyclopedia.setClassId(Long.parseLong(classId));
			indexEncyclopedia.setStatus(1);
			indexEncyclopedia.setEncyclopedia("");
			indexEncyclopedia.setUnit("");
			indexEncyclopedia.setReferenceRange("");
			indexEncyclopedia.setImplication("");
			indexEncyclopedia.setClinicalSign("");
			indexEncyclopedia.setAttention("");
			indexEncyclopedia.setNormalValue("");
			indexEncyclopedia.setCreatorId(user.getUserId());
			indexEncyclopedia.setCreatorName(user.getRealName());
			indexEncyclopedia.setModifierId(user.getUserId());
			indexEncyclopedia.setModifierName(user.getRealName());
			indexDao.insertEncyclopedia(indexEncyclopedia);
		}

		IndexDto dto = null;
		try {
			dto = indexDao.retrieveDtoByOriginalId(id);
		} catch (Exception e) {
			LOGGER.error("retrieveDtoByOriginalId error;id=" + id);
			throw e;
		}

		// 获取检验大类的数据
		List<TestingClass> classList = testingClassService.getAll();
		Map<Long, String> classMap = new HashMap<>();
		for (TestingClass tc : classList) {
			classMap.put(tc.getId(), tc.getName());
		}

		Map<String, Object> map = new HashMap<>();
		map.put("dto", dto);
		map.put("originalName", originalName);
		map.put("name", name);
		map.put("classMap", classMap);
		return map;
	}

	public ReturnData edit(String originalId, String classId, String normalName, String mutiBox, String implication,
			String normalValue, String clinicalSign, String attention, User user) {
		// 查找当前标准名称是否存在index表中
		Index index = indexDao.retrieveOjbectByName(normalName);

		Long indexId = 0l;
		if (index == null) {
			indexId = createIndex(normalName, user);
			LOGGER.info("Index create success, id=" + indexId);
		} else {
			indexId = index.getId();
			LOGGER.info("Index exist, id=" + indexId);
		}

		// 如果勾选了mutiBox则批量修改原始指标，否则修改当前指标
		Long classIdLong = Long.parseLong(classId);
		Long originalIdLong = Long.parseLong(originalId);
		if (mutiBox != null && mutiBox.equals("on")) {
			indexDao.updateOriginal(originalIdLong, classIdLong, indexId, 1);
			LOGGER.info("muti update ");
		} else {
			indexDao.updateOriginal(originalIdLong, classIdLong, indexId, 0);
			LOGGER.info("mutiBox = " + mutiBox);
		}

		// 根据classId和indexId获取百科数据，如果不存在则新增，存在则修改
		setEncyclopedia(classIdLong, indexId, implication, normalValue, clinicalSign, attention, user);

		return ReturnUtil.success();
	}

	private void setEncyclopedia(Long classIdLong, Long indexId, String implication, String normalValue,
			String clinicalSign, String attention, User user) {
		IndexEncyclopedia ie = indexDao.retrieveEncyclopediaByClassIdAndIndexId(classIdLong, indexId);

		if (ie == null) {
			createEncyclopedia(classIdLong, indexId, implication, normalValue, clinicalSign, attention, user);
		} else {
			updateEncyclopedia(ie, implication, normalValue, clinicalSign, attention, user);
		}
	}

	private void updateEncyclopedia(IndexEncyclopedia ie, String implication, String normalValue, String clinicalSign,
			String attention, User user) {
		ie.setImplication(implication);
		ie.setNormalValue(normalValue);
		ie.setClinicalSign(clinicalSign);
		ie.setAttention(attention);
		ie.setModifierId(user.getUserId());
		ie.setModifierName(user.getRealName());

		indexDao.updateEncyclopedia(ie);
	}

	private void createEncyclopedia(Long classId, Long indexId, String implication, String normalValue,
			String clinicalSign, String attention, User user) {
		IndexEncyclopedia ie = new IndexEncyclopedia();
		ie.setIndexId(indexId);
		ie.setClassId(classId);
		ie.setStatus(1);
		ie.setEncyclopedia("");
		ie.setUnit("");
		ie.setReferenceRange("");
		ie.setImplication(implication);
		ie.setClinicalSign(clinicalSign);
		ie.setAttention(attention);
		ie.setNormalValue(normalValue);
		ie.setCreatorId(user.getUserId());
		ie.setCreatorName(user.getRealName());
		ie.setModifierId(user.getUserId());
		ie.setModifierName(user.getRealName());

		indexDao.insertEncyclopedia(ie);
	}

	private Long createIndex(String normalName, User user) {
		Index index = new Index();
		index.setName(normalName);
		index.setCreatorId(user.getUserId());
		index.setCreatorName(user.getRealName());
		index.setModifierId(user.getUserId());
		index.setModifierName(user.getRealName());

		return indexDao.insert(index);
	}

	public ReturnData encyclopediaImport(MultipartFile file, User user) throws Exception {

		InputStream inputStream = null;
		Workbook workbook = null;

		try {
			StringBuffer errMsg = new StringBuffer();

			// 获取文件流，解析文件
			inputStream = file.getInputStream();

			workbook = new XSSFWorkbook(inputStream);
			Sheet sheet = workbook.getSheetAt(0);

			// 获取指标、大类列表
			Map<String, Long> indexesMap = getIndexesMap();

			Map<String, Long> classMap = getClassMap();

			// 初始化数据格式
			List<IndexDto> dtos = new ArrayList<>();

			for (Row row : sheet) {
				if (row.getCell(0) == null || row.getCell(0).getStringCellValue().isEmpty()) {
					break;
				}
				String indexName = row.getCell(0).getStringCellValue().trim();
				if ("jczbmc".equals(indexName)) {
					continue;
				}

				row.getCell(1).setCellType(Cell.CELL_TYPE_STRING);
				String normalValue = row.getCell(1) == null ? ""
						: row.getCell(1).getStringCellValue().replace("\r", "");
				String implication = row.getCell(2) == null ? ""
						: row.getCell(2).getStringCellValue().replace("\r", "");
				String clinicalSign = row.getCell(3) == null ? ""
						: row.getCell(3).getStringCellValue().replace("\r", "");
				String attention = row.getCell(4) == null ? "" : row.getCell(4).getStringCellValue().replace("\r", "");
				if (row.getCell(5) == null) {
					errMsg.append(indexName);
					errMsg.append(",");
					continue;
				}
				String className = row.getCell(5).getStringCellValue();

				IndexDto dto = new IndexDto();
				dto.setIndexId(getIndexIdByName(indexesMap, indexName, user));
				dto.setClassId(getClassIdByName(classMap, className, user));
				dto.setNormalValue(normalValue);
				dto.setImplication(implication);
				dto.setClinicalSign(clinicalSign);
				dto.setAttention(attention);

				dtos.add(dto);
			}

			if (errMsg.length() > 0) {
				errMsg.indexOf("以下检验大类为空：", 0);
				ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
				rc.setDesc(errMsg.toString());
				return ReturnUtil.fail(rc);
			}

			// 数据维护
			persistData(dtos, user);

		} catch (Exception e) {
			throw e;
		} finally {
			workbook.close();
			inputStream.close();
		}
		return ReturnUtil.success();
	}

	public static void main(String[] args) {
		System.out.println("a\r\nb".replace("\r", ""));
	}

	private void persistData(List<IndexDto> dtos, User user) {
		for (IndexDto dto : dtos) {
			setEncyclopedia(dto.getClassId(), dto.getIndexId(), dto.getImplication(), dto.getNormalValue(),
					dto.getClinicalSign(), dto.getAttention(), user);
		}
	}

	private Long getClassIdByName(Map<String, Long> classMap, String className, User user) {
		if (classMap.get(className) != null) {
			return classMap.get(className);
		}

		return testingClassService.createClass(className, "", "", user);
	}

	private Long getIndexIdByName(Map<String, Long> indexesMap, String indexName, User user) {
		if (indexesMap.get(indexName) != null) {
			return indexesMap.get(indexName);
		}

		return createIndex(indexName, user);
	}

	private Map<String, Long> getClassMap() {
		List<TestingClass> list = testingClassService.getAll();
		Map<String, Long> map = new HashMap<>();
		for (TestingClass t : list) {
			map.put(t.getName(), t.getId());
		}
		return map;
	}

	private Map<String, Long> getIndexesMap() {
		List<Index> list = indexDao.retrieveList();
		Map<String, Long> map = new HashMap<>();
		for (Index index : list) {
			map.put(index.getName(), index.getId());
		}
		return map;
	}

	@Autowired
	private MigrateSwitch migrateSwitch;

	public ReturnData submitServer() throws Exception {

		if (!SubmitStatus.getSubmitRecords().contains(SubmitStatus.TYPE_INSPECTION)) {

			// 该功能设置为运行中
			SubmitStatus.addSubmitRecords(SubmitStatus.TYPE_INSPECTION);

			// 同步指标百科
			migrateSwitch.migrateByCode(MigrateCode.INSPECTION_INFO);

			// 同步原始指标
			migrateSwitch.migrateByCode(MigrateCode.INSPECTION_ORIGINAL);

			// 同步指标维表
			migrateSwitch.migrateByCode(MigrateCode.INSPECTION_DIMENSIOIN);

			// 同步检验大类
			migrateSwitch.migrateByCode(MigrateCode.INSPECTION_CLASS);

			// 同步检验大类指标对应关系
			migrateSwitch.migrateByCode(MigrateCode.INSPECTION_CLASS_RELATION);

			// 运行指标脚本
			BusinessUtil.excuteShell(new String[] { indexFileScript });

			LOGGER.info("infoFileScript success!");

			// 该功能从运行中去除
			SubmitStatus.removeSubmitRecords(SubmitStatus.TYPE_INSPECTION);

		}
		return ReturnUtil.success();
	}

	public ReturnData getEncyclopediaByIndex(String classId, String normalName) {

		IndexEncyclopedia ie = indexDao.retrieveEncyclopediaByClassIdAndNormalName(classId, normalName);

		Map<String, Object> data = new HashMap<>();
		data.put("ie", ie);
		return ReturnUtil.success(data);
	}

	public void encyclopediaExport(HttpServletResponse resp) throws Exception {
		// 设置respons的头信息
		RespHeaderUtil.setXlsxResp(resp, "指标百科");

		Workbook workbook = new XSSFWorkbook(); // 创建文档

		List<IndexDto> inspectionList = indexDao.retrieveEncyclopediaDto();

		Sheet sheet = workbook.createSheet("指标百科"); // 创建Sheet
		// 循环写入数据
		Cell cell = null;
		List<String> inspcetionClass = new ArrayList<>();
		for (int i = 0, j = 0; i < inspectionList.size(); i++) {
			IndexDto inspection = inspectionList.get(i);

			if (!inspcetionClass.contains(inspection.getIndexId() + ";" + inspection.getClassId())) {
				Row row = sheet.createRow(j);
				cell = row.createCell(0);
				cell.setCellValue(inspection.getNormalName());
				cell = row.createCell(1);
				cell.setCellValue(inspection.getNormalValue());
				cell = row.createCell(2);
				cell.setCellValue(inspection.getImplication());
				cell = row.createCell(3);
				cell.setCellValue(inspection.getClinicalSign());
				cell = row.createCell(4);
				cell.setCellValue(inspection.getAttention());
				cell = row.createCell(5);
				cell.setCellValue(inspection.getClassName());

				inspcetionClass.add(inspection.getIndexId() + ";" + inspection.getClassId());
				j++;
			}
		}

		OutputStream os = resp.getOutputStream();
		workbook.write(os);

		os.close();
		workbook.close();
	}

	public ReturnData initSynonymy() throws Exception {
		indexDao.initSynonymy();
		return ReturnUtil.success();
	}
}
